﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mozlite.Components
{
    /// <summary>
    /// 内容模型管理类。
    /// </summary>
    public static class ContentModules
    {
        /// <summary>
        /// 注册模型。
        /// </summary>
        public static void Register()
        {
            var modules = Cores.FindType<IContentModule>();
            modules.Save();
        }
        private static bool Save(this List<IContentModule> modules)
        {
            if (modules.Count == 0)
                return true;
            return Database.BeginTransaction<bool>(transaction =>
            { 
                transaction.ExecuteNonQuery("DELETE FROM moz_Modules;");
                foreach (var module in modules)
                {
                    if(module.Enabled)
                    {
                        transaction.ExecuteNonQuery("INSERT INTO moz_Modules(ModuleName,GroupKey,DefaultUrl,PagerUrl,DetailUrl,BackendUrl,BackendPagerUrl,BackendEditUrl,BackendPublicUrl,ModuleID,Version,IsSystem,CategoryTableName,ItemTableName,Enabled)VALUES(@ModuleName,@GroupKey,@DefaultUrl,@PagerUrl,@DetailUrl,@BackendUrl,@BackendPagerUrl,@BackendEditUrl,@BackendPublicUrl,@ModuleID,@Version,@IsSystem,@CategoryTableName,@ItemTableName,@Enabled);", new
                        {
                            ModuleName = module.ModuleName,
                            GroupKey = module.GroupKey,
                            DefaultUrl = module.DefaultUrl,
                            PagerUrl = module.PagerUrl,
                            DetailUrl = module.DetailUrl,
                            BackendUrl = module.BackendUrl,
                            BackendPagerUrl = module.BackendPagerUrl,
                            BackendEditUrl = module.BackendEditUrl,
                            BackendPublicUrl = module.BackendPublicUrl,
                            ModuleID = module.ModuleID,
                            Version = module.Version.ToString(),
                            IsSystem = module.GroupKey.StartsWith("SYS_"),
                            CategoryTableName = module.CategoryTableName,
                            ItemTableName = module.ItemTableName,
                            Enabled = module.Enabled
                        });
                    }
                }
                return true;
            });
        }
        private const string cacheKey = "CategoryModules::All";
        private const string groupKey = "CategoryModules::GroupAll";
        /// <summary>
        /// 加载所有模型。
        /// </summary>
        /// <returns>返回模型列表。</returns>
        public static Dictionary<Guid, ContentModule> Load()
        {
            return Caches.Get<Dictionary<Guid, ContentModule>>(cacheKey, () =>
            {
                var modules = new Dictionary<Guid, ContentModule>();
                using (var reader = Database.ExecuteReader("SELECT * FROM moz_Modules")) {
                    while (reader.Read()) {
                        var module = reader.As<ContentModule>();
                        modules.Add(module.ModuleID, module);
                    }
                }
                Caches.Max(cacheKey, modules);
                return modules;
            });
        }
        /// <summary>
        /// 按分组加载。
        /// </summary>
        /// <returns>返回模型列表。</returns>
        public static Dictionary<string, List<ContentModule>> LoadGroup()
        {
            return Caches.Get<Dictionary<string, List<ContentModule>>>(groupKey, () =>
            {
                var modules = new Dictionary<string, List<ContentModule>>(StringComparer.OrdinalIgnoreCase);
                using (var reader = Database.ExecuteReader("SELECT * FROM moz_Modules"))
                {
                    while (reader.Read())
                    {
                        var module = reader.As<ContentModule>();
                        if (!modules.ContainsKey(module.GroupKey))
                            modules.Add(module.GroupKey, new List<ContentModule>());
                        modules[module.GroupKey].Add(module);
                    }
                }
                Caches.Max(groupKey, modules, new System.Web.Caching.CacheDependency(null, new string[] { cacheKey }));
                return modules;
            });
        }
        /// <summary>
        /// 获取模型列表。
        /// </summary>
        /// <param name="groupKey">群组键。</param>
        /// <returns>返回列表。</returns>
        public static List<ContentModule> GetModules(string groupKey)
        {
            List<ContentModule> modules;
            LoadGroup().TryGetValue(groupKey, out modules);
            return modules;
        }
        /// <summary>
        /// 获取模型实例。
        /// </summary>
        /// <param name="moduleID">模型ID。</param>
        /// <returns>返回模型实例对象。</returns>
        public static ContentModule Get(Guid moduleID)
        {
            ContentModule module;
            Load().TryGetValue(moduleID, out module);
            return module;
        }
        /// <summary>
        /// 删除模型。
        /// </summary>
        /// <param name="moduleID">模型ID。</param>
        /// <param name="cascade">是否级联删除，会删除下级分类以及分类子项，请慎用。</param>
        /// <returns>返回删除结果。</returns>
        public static bool Delete(Guid moduleID, bool cascade = false)
        {
            var module = Get(moduleID);
            if(module == null || module.IsSystem)
                return false;
            if(cascade && module.ItemTableName.HasValue() && module.CategoryTableName.HasValue())
            {
                return Database.BeginTransaction<bool>(transaction =>
                {
                    transaction.ExecuteNonQuery("DELETE FROM {0} WHERE CategoryID IN(SELECT CategoryID FROM {1} WHERE ModuleID = @ModuleID);".FormatWith(module.ItemTableName, module.CategoryTableName), new { ModuleID = moduleID });
                    transaction.ExecuteNonQuery("DELETE FROM {0} WHERE ModuleID = @ModuleID", new { ModuleID = moduleID });
                    transaction.ExecuteNonQuery("DELETE FROM moz_Modules WHERE ModuleID = @ModuleID", new { ModuleID = moduleID });
                    return true;
                });
            }
            return Database.ExecuteNonQuery("DELETE FROM moz_Modules WHERE ModuleID = @ModuleID", new { ModuleID = moduleID });
        }
    }
}
